package braden.cis.uab.edu.automaton;

import java.util.HashSet;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.widget.Toast;
import braden.cis.uab.edu.R;

public class StepTestDrawingPanel extends AbstractDrawingPanel {

	private Automaton automatonToTest;
	private Context context;
	private char[] lettersToTest;
	private int currentIndex;
	private HashSet<State> currentStates;
	private int stepCounter;

	public StepTestDrawingPanel(Context context, Automaton automatonToTest,
			String stringToTest) {
		super(context);

		this.automatonToTest = automatonToTest;
		this.context = context;
		lettersToTest = stringToTest.toCharArray();
		currentIndex = 0;
		stepCounter = 0;
		currentStates = new HashSet<State>();
		currentStates.add(automatonToTest.getStartState());
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		synchronized (getDrawingThread().getSurfaceHolder()) {

			// if the screen was released
			if (event.getAction() == MotionEvent.ACTION_UP) {
				WindowManager wm = (WindowManager) context
						.getSystemService(Context.WINDOW_SERVICE);
				if (event.getX() >= wm.getDefaultDisplay().getWidth() / 2) {
					if (currentIndex < lettersToTest.length) {
						if (stepCounter % 2 == 0) {
							HashSet<State> statesToCheck = new HashSet<State>();
							statesToCheck.addAll(currentStates);
							for (State state : statesToCheck) {
								currentStates.addAll(automatonToTest
										.getNextStatesAfterEpsilonJump(state));
							}
							Toast.makeText(context, "After epsilon jumps", Toast.LENGTH_LONG).show();
						} else {
							HashSet<State> statesToCheck = new HashSet<State>();
							statesToCheck.addAll(currentStates);
							currentStates.clear();
							for (State state : statesToCheck) {
								currentStates.addAll(automatonToTest
										.getNextStates(state,
												lettersToTest[currentIndex]));
							}
							Toast.makeText(context, "After transitioning on character " + lettersToTest[currentIndex], Toast.LENGTH_LONG).show();
							currentIndex++;
						}
						stepCounter++;
					} else {

					}
				} else {
					Toast.makeText(context, "Left", Toast.LENGTH_LONG).show();
				}
			}
		}
		return true;
	}

	@Override
	public void onDraw(Canvas canvas) {
		canvas.drawColor(Color.WHITE);
		Paint transitionPaint = new Paint();
		transitionPaint.setColor(Color.BLACK);
		transitionPaint.setStyle(Paint.Style.STROKE);

		Paint textPaint = new Paint();
		textPaint.setColor(Color.BLACK);
		textPaint.setStyle(Paint.Style.STROKE);
		textPaint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));

		for (Transition transition : getTransitions()) {

			State start = transition.getStartState();
			State end = transition.getEndState();

			// if the transition has an opposing transition
			if (transition.hasOpposite()) {

				// here we are translating the lines coordinates a distance of
				// 10dip away from their original positions. This is done so
				// that its opposing transition does not overlap.
				// an explanation of this formula can be found here:
				// http://stackoverflow.com/questions/11253626/function-to-translate-end-coordinates-of-a-line
				float newStartX = (start.getX()
						+ (10 * ((-(end.getY() - start.getY())) / (Math
								.abs((-(end.getY() - start.getY())))))) + start
						.getGraphic().getWidth() / 2);
				float newStartY = (start.getY()
						+ (10 * ((end.getX() - start.getX()) / (Math.abs((end
								.getX() - start.getX()))))) + start
						.getGraphic().getHeight() / 2);
				float newEndX = (end.getX()
						+ (10 * ((-(end.getY() - start.getY())) / (Math
								.abs((-(end.getY() - start.getY())))))) + end
						.getGraphic().getWidth() / 2);
				float newEndY = (end.getY()
						+ (10 * ((end.getX() - start.getX()) / (Math.abs(end
								.getX()
								- start.getX())))) + end.getGraphic()
						.getHeight() / 2);

				// draw the translated line to the canvas
				canvas.drawLine(newStartX, newStartY, newEndX, newEndY,
						transitionPaint);

				// draw the transition characters for this transition
				canvas.drawText(transition.getLabelString(),
						(newStartX + newEndX) / 2, (newStartY + newEndY) / 2,
						textPaint);
				// if the transition is a loop to the same state
			} else if (end.equals(start)) {

				// create an oval
				RectF oval = new RectF();
				float top = 0;
				float left = 0;
				float right = 0;

				// if the graphic is close to the top of the screen...
				if (start.getY() + start.getGraphic().getHeight() / 2 - 65 < 0 + textPaint
						.getTextSize()) {

					// we want the loop and text to be drawn below the graphic
					top = start.getY() + start.getGraphic().getHeight() / 2
							+ 65;
					canvas.drawText(transition.getLabelString(), ((transition
							.getStartX() + transition.getEndX()) / 2)
							- textPaint
									.measureText(transition.getLabelString())
							/ 2, top + textPaint.getTextSize(), textPaint);
					// if the graphic is not close to the top...
				} else {
					// we will draw the loop and text above the graphic
					top = start.getY() + start.getGraphic().getHeight() / 2
							- 65;
					canvas.drawText(transition.getLabelString(), ((transition
							.getStartX() + transition.getEndX()) / 2)
							- textPaint
									.measureText(transition.getLabelString())
							/ 2, top - textPaint.getTextSize(), textPaint);
				}

				if (start.isInitial()) {
					left = start.getX() + start.getGraphic().getWidth() / 2 - 5;
					right = start.getX() + start.getGraphic().getWidth() / 2
							+ 25;
				} else {
					left = start.getX() + start.getGraphic().getWidth() / 2
							- 15;
					right = start.getX() + start.getGraphic().getWidth() / 2
							+ 15;
				}
				oval.set(left, top, right, start.getY()
						+ start.getGraphic().getHeight() / 2);
				canvas.drawOval(oval, transitionPaint);

			} else {
				canvas.drawLine(transition.getStartX(), transition.getStartY(),
						transition.getEndX(), transition.getEndY(),
						transitionPaint);

				canvas.drawText(transition.getLabelString(), (transition
						.getStartX() + transition.getEndX()) / 2, (transition
						.getStartY() + transition.getEndY()) / 2, textPaint);
			}
		}
		Bitmap bitmap = null;
		for (State graphic : getGraphics()) {
			boolean isCurrentState =false;
			for (State state : currentStates) {
				if (state.getLabel() == graphic.getLabel()) {
					isCurrentState = true;
				}
			}
			if (isCurrentState) {
				bitmap = BitmapFactory.decodeResource(context.getResources(),
						R.drawable.green_state);
			} else {
				bitmap = graphic.getGraphic();
			}
			canvas.drawBitmap(bitmap, graphic.getX(), graphic.getY(), null);
			String label = "q" + Integer.toString(graphic.getLabel());
			float x = 0;
			if (graphic.isInitial()) {
				x = graphic.getX() + graphic.getGraphic().getWidth() / 2
						- transitionPaint.measureText(label) / 2 + 10;
			} else {
				x = graphic.getX() + graphic.getGraphic().getWidth() / 2
						- transitionPaint.measureText(label) / 2;
			}
			canvas.drawText(label, x, graphic.getY()
					+ graphic.getGraphic().getHeight() / 2
					+ transitionPaint.getTextSize() / 4, transitionPaint);
		}
	}
}
